package org.fat.nerd.actd.sharding.config;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

/**
 * Mybatis & Mapper & PageHelper 配置
 */
@Slf4j
@Configuration
@MapperScan({"org.fat.nerd.actd.sharding.dao"})
public class MybatisConfigurer {

    @Value("${spring.datasource.url}")
    private String defaultJdbcUrl;
    @Value("${spring.datasource.username}")
    private String defaultUsername;
    @Value("${spring.datasource.password}")
    private String defaultPassword;
    @Value("${spring.datasource.driver-class-name}")
    private String defaultDriverClassName;


    /**
     * 配置事务
     *
     * @param dynamicDataSource
     * @return
     */
    @Bean
    @Qualifier("transactionManager")
    public PlatformTransactionManager txManager(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }

    /**
     * 配置文件yml中的默认数据源
     *
     * @return
     */
    @Bean(name = "defaultDataSource")
    public DataSource getDefaultDataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(defaultJdbcUrl);
        dataSource.setUsername(defaultUsername);
        dataSource.setPassword(defaultPassword);
        dataSource.setDriverClassName(defaultDriverClassName);
        dataSource.setMaximumPoolSize(100);
        dataSource.setMinimumIdle(10);
        dataSource.setConnectionTimeout(5000);
        dataSource.setConnectionTestQuery("SELECT 1");
        dataSource.setIdleTimeout(60 * 1000);
        dataSource.setMaxLifetime(10 * 60 * 1000);
        return dataSource;
    }

    /**
     * 将动态数据源对象放入spring中管理
     *
     * @return
     */
    @Bean
    public DynamicDataSource dynamicDataSource() {
        log.info("将Hikari数据源放入默认动态数据源对象中");
        return new DynamicDataSource(getDefaultDataSource());
    }

    /**
     * 数据库连接会话工厂
     *
     * @param dynamicDataSource 自定义动态数据源
     * @return
     * @throws Exception
     */
    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dynamicDataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath*:mapper/*.xml"));
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setLogImpl(org.apache.ibatis.logging.log4j2.Log4j2Impl.class);
        configuration.setUseGeneratedKeys(true);
        configuration.setUseColumnLabel(true);
        bean.setConfiguration(configuration);
        return bean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
